{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 24,
   "metadata": {},
   "outputs": [],
   "source": [
    "import os\n",
    "import re\n",
    "from pyvis.network import Network\n",
    "from pyltp import Segmentor,Postagger,Parser,SementicRoleLabeller"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "metadata": {},
   "outputs": [],
   "source": [
    "def parser_main(sentence):\n",
    "    LTP_DIR=\"./ltp_data_v3.4.0\"\n",
    "    segmentor=Segmentor(os.path.join(LTP_DIR,\"cws.model\"))\n",
    "    postagger=Postagger(os.path.join(LTP_DIR,\"pos.model\"))\n",
    "    parser=Parser(os.path.join(LTP_DIR,\"parser.model\"))\n",
    "    labeller=SementicRoleLabeller(os.path.join(LTP_DIR,\"pisrl_win.model\"))\n",
    "    words=list(segmentor.segment(sentence))\n",
    "    postags=list(postagger.postag(words))\n",
    "    arcs=parser.parse(words,postags)\n",
    "    roles=labeller.label(words,postags,arcs)\n",
    "    roles_dict={key:{sub_key:[sub_key, *value] for sub_key,value in sub_data} for key,sub_data in roles}\n",
    "    return words, postags,arcs,roles_dict"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "分词结果: ['苏轼', '是', '宋朝', '的', '著名', '文学家', '，', '黄庭坚', '是', '苏轼', '的', '好', '朋友', '。', '苏轼', '擅长', '写', '词', '，', '而', '黄庭坚', '擅长', '写', '诗', '。', '黄庭坚', '游览', '黄州', '，', '并', '赞叹', '黄山', '之', '美', '。', '黄庭坚', '探望', '苏轼', '，', '并', '一起', '吟诗', '作', '对', '。']\n",
      "语义角色标注结果: {1: {'A0': ['A0', 0, 0], 'A1': ['A1', 2, 5]}, 8: {'A0': ['A0', 7, 7], 'A1': ['A1', 9, 12]}, 15: {'A0': ['A0', 14, 14]}, 16: {'A1': ['A1', 17, 17]}, 21: {'A0': ['A0', 20, 20], 'A1': ['A1', 23, 23]}, 22: {'A1': ['A1', 23, 23]}, 26: {'A0': ['A0', 25, 25], 'A1': ['A1', 27, 27]}, 30: {'DIS': ['DIS', 29, 29], 'A1': ['A1', 31, 33]}, 36: {'A0': ['A0', 35, 35], 'A1': ['A1', 37, 37]}, 41: {'A0': ['A0', 35, 35], 'DIS': ['DIS', 39, 39], 'ADV': ['ADV', 40, 40]}, 42: {'ADV': ['ADV', 40, 40]}}\n"
     ]
    }
   ],
   "source": [
    "text=\"苏轼是宋朝的著名文学家，黄庭坚是苏轼的好朋友。苏轼擅长写词，而黄庭坚擅长写诗。黄庭坚游览黄州，并赞叹黄山之美。黄庭坚探望苏轼，并一起吟诗作对。\"\n",
    "words,postags,arcs,roles_dict=parser_main(text)\n",
    "print(\"分词结果:\",words)\n",
    "print(\"语义角色标注结果:\",roles_dict)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 28,
   "metadata": {},
   "outputs": [],
   "source": [
    "def ruler(words,postags,roles_dict,role_index):\n",
    "    v=words[role_index]\n",
    "    role_info=roles_dict[role_index]\n",
    "    if'A0'in role_info.keys()and'A1'in role_info.keys():\n",
    "        s=''.join([words[word_index]for word_index in range(role_info['A0'][1],role_info['A0'][2]+1)if postags[word_index][0]not in['w','u','x']and words[word_index]])\n",
    "        if s and o:\n",
    "            return'1',[s,v,o]\n",
    "    return'4',[]  "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 29,
   "metadata": {},
   "outputs": [],
   "source": [
    "def triples_main(text):\n",
    "    sentences=[sentence for sentence in re.split(r'[？?！!。；;：:\\n\\r]',text)if sentence]\n",
    "    svos=[]\n",
    "    for index,sentence in enumerate(sentences):\n",
    "        words,postags,arcs,roles_dict=parser_main(sentence)\n",
    "        for index in range(len(postags)):\n",
    "            if index in roles_dict:\n",
    "                flag,triple=ruler(words,postags,roles_dict,index)\n",
    "                if flag=='1':\n",
    "                    svos.append(triple)\n",
    "    return svos"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 30,
   "metadata": {},
   "outputs": [
    {
     "ename": "NameError",
     "evalue": "name 'o' is not defined",
     "output_type": "error",
     "traceback": [
      "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[1;31mNameError\u001b[0m                                 Traceback (most recent call last)",
      "\u001b[1;32m<ipython-input-30-3322bd8352ea>\u001b[0m in \u001b[0;36m<module>\u001b[1;34m()\u001b[0m\n\u001b[1;32m----> 1\u001b[1;33m \u001b[0msvos\u001b[0m\u001b[1;33m=\u001b[0m\u001b[0mtriples_main\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mtext\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m      2\u001b[0m \u001b[0mprint\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;34m\"文本的三元组:svos={0}\"\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mformat\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0msvos\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n",
      "\u001b[1;32m<ipython-input-29-1be147bc4284>\u001b[0m in \u001b[0;36mtriples_main\u001b[1;34m(text)\u001b[0m\n\u001b[0;32m      6\u001b[0m         \u001b[1;32mfor\u001b[0m \u001b[0mindex\u001b[0m \u001b[1;32min\u001b[0m \u001b[0mrange\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mlen\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mpostags\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m      7\u001b[0m             \u001b[1;32mif\u001b[0m \u001b[0mindex\u001b[0m \u001b[1;32min\u001b[0m \u001b[0mroles_dict\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m----> 8\u001b[1;33m                 \u001b[0mflag\u001b[0m\u001b[1;33m,\u001b[0m\u001b[0mtriple\u001b[0m\u001b[1;33m=\u001b[0m\u001b[0mruler\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mwords\u001b[0m\u001b[1;33m,\u001b[0m\u001b[0mpostags\u001b[0m\u001b[1;33m,\u001b[0m\u001b[0mroles_dict\u001b[0m\u001b[1;33m,\u001b[0m\u001b[0mindex\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m      9\u001b[0m                 \u001b[1;32mif\u001b[0m \u001b[0mflag\u001b[0m\u001b[1;33m==\u001b[0m\u001b[1;34m'1'\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m     10\u001b[0m                     \u001b[0msvos\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mappend\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mtriple\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n",
      "\u001b[1;32m<ipython-input-28-0ee9f7eba563>\u001b[0m in \u001b[0;36mruler\u001b[1;34m(words, postags, roles_dict, role_index)\u001b[0m\n\u001b[0;32m      4\u001b[0m     \u001b[1;32mif\u001b[0m\u001b[1;34m'A0'\u001b[0m\u001b[1;32min\u001b[0m \u001b[0mrole_info\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mkeys\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;32mand\u001b[0m\u001b[1;34m'A1'\u001b[0m\u001b[1;32min\u001b[0m \u001b[0mrole_info\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mkeys\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m      5\u001b[0m         \u001b[0ms\u001b[0m\u001b[1;33m=\u001b[0m\u001b[1;34m''\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mjoin\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m[\u001b[0m\u001b[0mwords\u001b[0m\u001b[1;33m[\u001b[0m\u001b[0mword_index\u001b[0m\u001b[1;33m]\u001b[0m\u001b[1;32mfor\u001b[0m \u001b[0mword_index\u001b[0m \u001b[1;32min\u001b[0m \u001b[0mrange\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mrole_info\u001b[0m\u001b[1;33m[\u001b[0m\u001b[1;34m'A0'\u001b[0m\u001b[1;33m]\u001b[0m\u001b[1;33m[\u001b[0m\u001b[1;36m1\u001b[0m\u001b[1;33m]\u001b[0m\u001b[1;33m,\u001b[0m\u001b[0mrole_info\u001b[0m\u001b[1;33m[\u001b[0m\u001b[1;34m'A0'\u001b[0m\u001b[1;33m]\u001b[0m\u001b[1;33m[\u001b[0m\u001b[1;36m2\u001b[0m\u001b[1;33m]\u001b[0m\u001b[1;33m+\u001b[0m\u001b[1;36m1\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;32mif\u001b[0m \u001b[0mpostags\u001b[0m\u001b[1;33m[\u001b[0m\u001b[0mword_index\u001b[0m\u001b[1;33m]\u001b[0m\u001b[1;33m[\u001b[0m\u001b[1;36m0\u001b[0m\u001b[1;33m]\u001b[0m\u001b[1;32mnot\u001b[0m \u001b[1;32min\u001b[0m\u001b[1;33m[\u001b[0m\u001b[1;34m'w'\u001b[0m\u001b[1;33m,\u001b[0m\u001b[1;34m'u'\u001b[0m\u001b[1;33m,\u001b[0m\u001b[1;34m'x'\u001b[0m\u001b[1;33m]\u001b[0m\u001b[1;32mand\u001b[0m \u001b[0mwords\u001b[0m\u001b[1;33m[\u001b[0m\u001b[0mword_index\u001b[0m\u001b[1;33m]\u001b[0m\u001b[1;33m]\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m----> 6\u001b[1;33m         \u001b[1;32mif\u001b[0m \u001b[0ms\u001b[0m \u001b[1;32mand\u001b[0m \u001b[0mo\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m      7\u001b[0m             \u001b[1;32mreturn\u001b[0m\u001b[1;34m'1'\u001b[0m\u001b[1;33m,\u001b[0m\u001b[1;33m[\u001b[0m\u001b[0ms\u001b[0m\u001b[1;33m,\u001b[0m\u001b[0mv\u001b[0m\u001b[1;33m,\u001b[0m\u001b[0mo\u001b[0m\u001b[1;33m]\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m      8\u001b[0m     \u001b[1;32mreturn\u001b[0m\u001b[1;34m'4'\u001b[0m\u001b[1;33m,\u001b[0m\u001b[1;33m[\u001b[0m\u001b[1;33m]\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n",
      "\u001b[1;31mNameError\u001b[0m: name 'o' is not defined"
     ]
    }
   ],
   "source": [
    "svos=triples_main(text)\n",
    "print(\"文本的三元组:svos={0}\".format(svos))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 31,
   "metadata": {},
   "outputs": [],
   "source": [
    "def create_node(net,subs1,subs2):\n",
    "    if len(subs1)!=0:\n",
    "        for i in range(len(subs1)):\n",
    "            net.add_node(i,label=subs1[i],color=\"bule\")\n",
    "    if len(subs2)!=0:\n",
    "        for i in range(len(subs2)):\n",
    "            net.add_node(1000+i,label=subs2[i],color=\"green\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [],
   "source": [
    "def create_node_id_dic(net):\n",
    "    dic_node_id={}\n",
    "    for i in net.node_ids:\n",
    "        dic_node_id[str(net.node_map[i][\"label\"])]=i\n",
    "    return dic_node_id"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 32,
   "metadata": {},
   "outputs": [
    {
     "ename": "SyntaxError",
     "evalue": "invalid syntax (<ipython-input-32-360c66e0ce43>, line 1)",
     "output_type": "error",
     "traceback": [
      "\u001b[1;36m  File \u001b[1;32m\"<ipython-input-32-360c66e0ce43>\"\u001b[1;36m, line \u001b[1;32m1\u001b[0m\n\u001b[1;33m    defdef create_network(net,kg_list,node_id_dic):\u001b[0m\n\u001b[1;37m                        ^\u001b[0m\n\u001b[1;31mSyntaxError\u001b[0m\u001b[1;31m:\u001b[0m invalid syntax\n"
     ]
    }
   ],
   "source": [
    "defdef create_network(net,kg_list,node_id_dic):\n",
    "    for m in range(len(kg_list)):\n",
    "        try:\n",
    "            net.add_edge(node_id_dic[kg_list[m][0]],node_id_dic[kg_list[m][2]],label=kg_list[m][1],color=\"red\",width=2)\n",
    "        except AttributeError as e:\n",
    "            print(e,m)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Warning: When  cdn_resources is 'local' jupyter notebook has issues displaying graphics on chrome/safari. Use cdn_resources='in_line' or cdn_resources='remote' if you have issues viewing graphics in a notebook.\n"
     ]
    },
    {
     "ename": "NameError",
     "evalue": "name 'svos' is not defined",
     "output_type": "error",
     "traceback": [
      "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[1;31mNameError\u001b[0m                                 Traceback (most recent call last)",
      "\u001b[1;32m<ipython-input-20-cc037ddf81ea>\u001b[0m in \u001b[0;36m<module>\u001b[1;34m()\u001b[0m\n\u001b[0;32m      1\u001b[0m \u001b[0mnet\u001b[0m\u001b[1;33m=\u001b[0m\u001b[0mNetwork\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mnotebook\u001b[0m\u001b[1;33m=\u001b[0m\u001b[1;32mTrue\u001b[0m\u001b[1;33m,\u001b[0m\u001b[0mdirected\u001b[0m\u001b[1;33m=\u001b[0m\u001b[1;32mTrue\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m----> 2\u001b[1;33m \u001b[0msubs1\u001b[0m\u001b[1;33m=\u001b[0m\u001b[0mlist\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mset\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0msublist\u001b[0m\u001b[1;33m[\u001b[0m\u001b[1;36m0\u001b[0m\u001b[1;33m]\u001b[0m \u001b[1;32mfor\u001b[0m \u001b[0msublist\u001b[0m \u001b[1;32min\u001b[0m \u001b[0msvos\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m      3\u001b[0m \u001b[0msubs2\u001b[0m\u001b[1;33m=\u001b[0m\u001b[0mlist\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mset\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0msublist\u001b[0m\u001b[1;33m[\u001b[0m\u001b[1;36m2\u001b[0m\u001b[1;33m]\u001b[0m \u001b[1;32mfor\u001b[0m \u001b[0msublist\u001b[0m \u001b[1;32min\u001b[0m \u001b[0msvos\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m      4\u001b[0m \u001b[0mcreate_node\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mnet\u001b[0m\u001b[1;33m,\u001b[0m\u001b[0msub1\u001b[0m\u001b[1;33m,\u001b[0m\u001b[0msub2\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m      5\u001b[0m \u001b[0mdic_node_id\u001b[0m\u001b[1;33m=\u001b[0m\u001b[0mcreate_node_id_dic\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mnet\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n",
      "\u001b[1;31mNameError\u001b[0m: name 'svos' is not defined"
     ]
    }
   ],
   "source": [
    "net=Network(notebook=True,directed=True)\n",
    "subs1=list(set(sublist[0] for sublist in svos))\n",
    "subs2=list(set(sublist[2] for sublist in svos))\n",
    "create_node(net,sub1,sub2)\n",
    "dic_node_id=create_node_id_dic(net)\n",
    "create_network(net,svos,dic_node_id)\n",
    "net.show(\"my_network.html\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "metadata": {},
   "outputs": [],
   "source": [
    "def find_similar_semantics(net,node_id_dic,target_node):\n",
    "    target_node_id=node_id_dic[target_node]\n",
    "    adjacent_nodes=net.neighbors(target_node_id)\n",
    "    similar_semantics=[node_id_dic_inverse[node_id] for node_id in adjacent_nodes]\n",
    "    return similar_semantics"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "metadata": {},
   "outputs": [
    {
     "ename": "SyntaxError",
     "evalue": "invalid syntax (<ipython-input-22-1d2345d80721>, line 1)",
     "output_type": "error",
     "traceback": [
      "\u001b[1;36m  File \u001b[1;32m\"<ipython-input-22-1d2345d80721>\"\u001b[1;36m, line \u001b[1;32m1\u001b[0m\n\u001b[1;33m    node_id_dic_inverse={v: k for k,v in dic_node_id,'苏轼'}\u001b[0m\n\u001b[1;37m                                                    ^\u001b[0m\n\u001b[1;31mSyntaxError\u001b[0m\u001b[1;31m:\u001b[0m invalid syntax\n"
     ]
    }
   ],
   "source": [
    "node_id_dic_inverse={v: k for k,v in dic_node_id,'苏轼'}\n",
    "print(\"与目标词'苏轼'语义相关的词:\",similar)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.0"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
